import { buildQiniuUrl, getUploadKey, uploadToQiniu } from '@/services/upload';
import { EyeOutlined, PlusOutlined } from '@ant-design/icons';
import { Image, Modal, Upload, message } from 'antd';
import type { UploadFile } from 'antd/es/upload/interface';
import React, { useRef, useState } from 'react';
import { qiniuConfig } from '../../../config/qiniu';
import VideoPreviewModal, { VideoPreviewModalRef } from './VideoPreviewModal';

interface ImageUploadData {
  [key: string]: any;
  url?: string;
}

interface ImageUploadProps {
  value?: ImageUploadData[];
  maxSize?: number;
  uploadType?: string;
  onChange?: (list: ImageUploadData[]) => void;
  accept?: string;
  readonly?: boolean;
  showPreviewIcon?: string;
  showRemoveIcon?: string;
  max?: number;
  type?: string; // 文件夹类型
}

const ServerImageUploadFold: React.FC<ImageUploadProps> = React.forwardRef((props) => {
  const [visible, setVisible] = useState(false);
  const [previewImageUrl, setPreviewImageUrl] = useState('');
  const [messageApi, messageContextHolder] = message.useMessage();
  const maxSize = props?.maxSize || 1024 * 1024 * 10; // 默认最大为10M
  const videoPreviewModalRef = useRef<VideoPreviewModalRef>(null);

  const accept = React.useMemo(() => {
    // 默认上传图片
    if (!props.accept) {
      return 'image/*,application/pdf';
    }
    return props.accept;
  }, [props.accept]);

  const isPdf = (fileUrl: any) => {
    // 获取文件扩展名
    const fileExtension = fileUrl.split('.').pop().toLowerCase();
    // 判断文件类型
    return fileExtension === 'pdf';
  };

  const isVideo = (fileUrl: any) => {
    // 获取文件扩展名
    const fileExtension = fileUrl.split('.').pop().toLowerCase();
    // 判断文件类型
    return ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv'].includes(fileExtension);
  };

  const isImage = (fileUrl: any) => {
    // 获取文件扩展名
    const fileExtension = fileUrl.split('.').pop().toLowerCase();
    // 判断文件类型
    return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp'].includes(fileExtension);
  };

  /**
   * 预览
   */
  const handlePreview = (file: any) => {
    // 图片 url
    const fileUrl = file.url || file?.thumbUrl;
    // 判断文件类型
    const IsImage = isImage(fileUrl);
    const IsPdf = isPdf(fileUrl);
    const IsVideo = isVideo(fileUrl);

    if (IsImage) {
      // 图片类型
      setPreviewImageUrl(fileUrl);
      setVisible(true);
    } else if (IsVideo) {
      // 视频类型
      videoPreviewModalRef.current?.show(fileUrl);
    } else if (IsPdf) {
      // PDF 类型，直接打开新页面
      window.open(fileUrl, '_blank');
    } else {
      console.warn('Unsupported file type');
    }
  };

  /**
   * 自定义上传
   */
  const customUpload = React.useCallback(
    async (file: File) => {
      try {
        // 获取上传token
        const tokenResponse = await getUploadKey({
          type: props.type || 'image',
          upload_type: props.uploadType || 'normal',
          bucket: qiniuConfig.bucket,
        });

        if (tokenResponse.code !== 200) {
          messageApi.error('获取上传凭证失败');
          return;
        }

        const { token, key } = tokenResponse.data;

        // 上传到七牛
        const uploadResponse = await uploadToQiniu(file, token, key ?? '');

        if (uploadResponse.ok) {
          const result = await uploadResponse.json();
          if (result.key) {
            // 构建完整的文件URL
            const fileUrl = buildQiniuUrl(result.key);

            // 创建文件对象
            const fileObj = {
              uid: Date.now().toString(),
              name: file.name,
              status: 'done',
              url: fileUrl,
              size: file.size,
              type: file.type,
            };

            // 更新文件列表
            const currentValue = props.value || [];
            const newValue = [...currentValue, fileObj];
            props.onChange?.(newValue);

            messageApi.success('上传成功');
          } else {
            messageApi.error('上传失败');
          }
        } else {
          messageApi.error('上传失败');
        }
      } catch (error) {
        console.error('上传错误:', error);
        messageApi.error('上传失败');
      }
    },
    [props, qiniuConfig, messageApi],
  );

  /**
   * 更改
   */
  const handleChange = (fileInfo: any) => {
    console.log('fileInfo', fileInfo);

    // 过滤掉上传失败的文件
    const list = fileInfo.fileList.filter((v: UploadFile) => {
      if (v.status === 'error') {
        messageApi.error('上传失败');
        return false;
      }
      if (v.status === 'removed') {
        return false;
      }
      return true;
    });

    props.onChange?.(list);
  };

  /**
   * 删除
   */
  const handleRemove = (file: UploadFile) => {
    const currentValue = props.value || [];
    const newValue = currentValue.filter((item) => item.uid !== file.uid);
    props.onChange?.(newValue);
    return true;
  };

  const canUpload = (file: any) => {
    // 限制文件上传大小
    if (file.size > maxSize) {
      return false;
    } else {
      return file;
    }
  };

  /**
   * 上传前
   */
  const beforeUpload = React.useCallback(async (file: any) => {
    if (!canUpload(file)) {
      return false;
    }
    return file;
  }, []);

  const uploadProps: any = React.useMemo(() => {
    return {
      name: 'file',
      accept: accept,
      onChange: handleChange,
      onRemove: handleRemove,
      onPreview: handlePreview,
      beforeUpload,
      customRequest: customUpload,
      showUploadList: {
        showPreviewIcon: props.showPreviewIcon,
        showRemoveIcon: props.readonly ? false : props.showRemoveIcon,
      },
      multiple: true,
      maxCount: props.max || 999,
    };
  }, [props, accept, beforeUpload, customUpload]);

  const uploadButton = (
    <div>
      <PlusOutlined />
      <div>上传</div>
    </div>
  );

  return (
    <div>
      {/* 如果是只读的 使用Image 组件 */}
      {props.readonly && accept.includes('image') ? (
        <Image.PreviewGroup>
          {props.value?.map((item: any) => {
            return isPdf(item.url) ? (
              <div
                key={item.url}
                onClick={() => {
                  window.open(item.url, '_blank');
                }}
                style={{
                  cursor: 'pointer',
                  height: 100,
                  width: 100,
                  display: 'flex',
                  flexDirection: 'column',
                  alignItems: 'center',
                  justifyContent: 'center',
                  border: '1px solid #d9d9d9',
                  borderRadius: '6px',
                  backgroundColor: '#fafafa',
                }}
              >
                <EyeOutlined style={{ fontSize: 32, color: '#1890ff' }} />
                <span style={{ marginTop: 8, fontSize: 12 }}>PDF</span>
              </div>
            ) : isVideo(item.url) ? (
              <video width={100} height={100} src={item.url} controls key={item.url} />
            ) : (
              // 图片展示
              <Image width={100} height={100} src={item.url} key={item.url} />
            );
          })}
        </Image.PreviewGroup>
      ) : (
        <Upload
          listType="picture-card"
          {...uploadProps}
          fileList={props.value}
          disabled={props.readonly}
        >
          {(props.value?.length || 0) >= (props.max || 999) ? null : uploadButton}
        </Upload>
      )}
      {/* 预览弹窗 */}
      <Modal width={'40vw'} open={visible} footer={null} onCancel={() => setVisible(false)}>
        <img alt="img" style={{ width: '100%' }} src={previewImageUrl} />
      </Modal>
      <VideoPreviewModal ref={videoPreviewModalRef} />
      {messageContextHolder}
    </div>
  );
});

export default ServerImageUploadFold;
